package tech.waterism.algorithm;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.BooleanUtil;
import org.apache.commons.lang3.time.DateUtils;
import tech.waterism.dto.*;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

/**
 * 评价函数
 */
public class Evaluations {

    /**
     * 纳什系数
     * 洪量误差
     * 洪峰误差
     * 峰现误差
     */
    public static StatisticsInfoDto refreshStatisticsInfoForCalibration(List<ForecastDataDto> data, Date dtBeg,
                                                                        Date dtEnd, Integer clen, String unt) {
        double sumQReal = 0;
        double sumQFore = 0;
        int sumNum = 0;
        double peakQReal = -1;
        double peakQFore = -1;
        int peakTimeQReal = -1;
        int peakTimeQFore = -1;
        int num = 0;
        for (ForecastDataDto dataOne : data) {
            if (dataOne.getQReal() != null && dataOne.getQSim() != null) {
                sumQReal += dataOne.getQReal();
                sumQFore += dataOne.getQSim();

                if (peakQReal < dataOne.getQReal()) {
                    peakQReal = dataOne.getQReal();
                    peakTimeQReal = num;
                }
                if (peakQFore < dataOne.getQSim()) {
                    peakQFore = dataOne.getQSim();
                    peakTimeQFore = num;
                }
                sumNum++;
            }
            num++;
        }

        double absoluteErrorOfSumQ = sumQFore - sumQReal;
        if (sumQReal == 0) {
            sumQReal = 0.00001;
        }
        double relativeErrorOfSumQ = Math.abs(absoluteErrorOfSumQ / sumQReal);

        double absoluteErrorOfPeak = peakQFore - peakQReal;
        if (peakQReal == 0) {
            peakQReal = 0.00001;
        }
        double relativeErrorOfPeak = Math.abs(absoluteErrorOfPeak / peakQReal);
        int absoluteErrorOfPeakTime = peakTimeQFore - peakTimeQReal;

        double nashCoeff = getNashCoefficient(data, sumQReal, sumNum);

        StatisticsInfoDto statisticsInfo = new StatisticsInfoDto();
        statisticsInfo.setDtBeg(dtBeg);
        statisticsInfo.setDtEnd(dtEnd);
        statisticsInfo.setPeakQReal(peakQReal);
        statisticsInfo.setPeakTimeQRealIndex(peakTimeQReal);
        statisticsInfo.setPeakTimeQReal(data.get(peakTimeQReal).getDt());
        statisticsInfo.setSumQReal(sumQReal * CommonFun.multiKFromFlowToVolumn(clen, unt));
        statisticsInfo.setPeakQFore(peakQFore);
        if (peakTimeQFore >= 0) {
            statisticsInfo.setPeakTimeQForeIndex(peakTimeQFore);
            statisticsInfo.setPeakTimeQFore(data.get(peakTimeQFore).getDt());
        }
        statisticsInfo.setSumQFore(sumQFore * CommonFun.multiKFromFlowToVolumn(clen, unt));
        statisticsInfo.setRelativeErrorOfSumQ(relativeErrorOfSumQ);
        statisticsInfo.setAbsoluteErrorOfSumQ(absoluteErrorOfSumQ);
        statisticsInfo.setRelativeErrorOfPeak(relativeErrorOfPeak);
        statisticsInfo.setAbsoluteErrorOfPeak(absoluteErrorOfPeak);
        statisticsInfo.setAbsoluteErrorOfPeakTime(absoluteErrorOfPeakTime);
        statisticsInfo.setNashCoeff(nashCoeff);
        return statisticsInfo;
    }

    /**
     * 纳什系数
     * 洪量误差
     * 洪峰误差
     * 峰现误差
     */
    public static StatisticsInfoDto refreshStatisticsInfo(List<ForecastDataDto> data) {
        double sumQReal = 0;
        double sumQFore = 0;
        int sumNum = 0;
        double peakQReal = -1;
        double peakQFore = -1;
        int peakTimeQReal = -1;
        int peakTimeQFore = -1;
        int num = 0;
        for (ForecastDataDto dataOne : data) {
            if (dataOne.getQReal() != null && dataOne.getQSim() != null) {
                sumQReal += dataOne.getQReal();
                sumQFore += dataOne.getQSim();

                if (peakQReal < dataOne.getQReal()) {
                    peakQReal = dataOne.getQReal();
                    peakTimeQReal = num;
                }
                if (peakQFore < dataOne.getQSim()) {
                    peakQFore = dataOne.getQSim();
                    peakTimeQFore = num;
                }
                sumNum++;
            }
            num++;
        }

        double absoluteErrorOfSumQ = sumQFore - sumQReal;
        if (sumQReal == 0) {
            sumQReal = 0.00001;
        }
        double relativeErrorOfSumQ = 100 * absoluteErrorOfSumQ / sumQReal;

        double absoluteErrorOfPeak = peakQFore - peakQReal;
        if (peakQReal == 0) {
            peakQReal = 0.00001;
        }
        double relativeErrorOfPeak = 100 * absoluteErrorOfPeak / peakQReal;
        int absoluteErrorOfPeakTime = peakTimeQFore - peakTimeQReal;

        double nashCoeff = getNashCoefficient(data, sumQReal, sumNum);

        StatisticsInfoDto statisticsInfo = new StatisticsInfoDto();
        statisticsInfo.setPeakQReal(peakQReal);
        statisticsInfo.setPeakTimeQRealIndex(peakTimeQReal);
        statisticsInfo.setPeakTimeQReal(data.get(peakTimeQReal).getDt());
        statisticsInfo.setSumQReal(sumQReal);
        statisticsInfo.setPeakQFore(peakQFore);
        statisticsInfo.setPeakTimeQForeIndex(peakTimeQFore);
        statisticsInfo.setPeakTimeQFore(data.get(peakTimeQFore).getDt());
        statisticsInfo.setSumQFore(sumQFore);
        statisticsInfo.setRelativeErrorOfSumQ(relativeErrorOfSumQ);
        statisticsInfo.setAbsoluteErrorOfSumQ(absoluteErrorOfSumQ);
        statisticsInfo.setRelativeErrorOfPeak(relativeErrorOfPeak);
        statisticsInfo.setAbsoluteErrorOfPeak(absoluteErrorOfPeak);
        statisticsInfo.setAbsoluteErrorOfPeakTime(absoluteErrorOfPeakTime);
        statisticsInfo.setNashCoeff(nashCoeff);
        return statisticsInfo;
    }

    /**
     * 纳什系数
     * 洪量误差
     * 洪峰误差
     * 峰现误差
     */
    public static StatisticsInfoDto refreshStatisticsInfo(List<Double> realQ, List<Double> simQ) {
        double sumQReal = 0;
        double sumQFore = 0;
        int sumNum = 0;
        double peakQReal = -1;
        double peakQFore = -1;
        int peakTimeQReal = -1;
        int peakTimeQFore = -1;
        int num = 0;
        for (int i = 0; i < realQ.size(); i++) {
            if (realQ.get(i) != null && simQ.get(i) != null) {
                sumQReal += realQ.get(i);
                sumQFore += simQ.get(i);

                if (peakQReal < realQ.get(i)) {
                    peakQReal = realQ.get(i);
                    peakTimeQReal = num;
                }
                if (peakQFore < simQ.get(i)) {
                    peakQFore = simQ.get(i);
                    peakTimeQFore = num;
                }
                sumNum++;
            }
            num++;
        }
        double absoluteErrorOfSumQ = sumQFore - sumQReal;
        if (sumQReal == 0) {
            sumQReal = 0.00001;
        }
        double relativeErrorOfSumQ = 100 * absoluteErrorOfSumQ / sumQReal;

        double absoluteErrorOfPeak = peakQFore - peakQReal;
        if (peakQReal == 0) {
            peakQReal = 0.00001;
        }
        double relativeErrorOfPeak = 100 * absoluteErrorOfPeak / peakQReal;
        int absoluteErrorOfPeakTime = peakTimeQFore - peakTimeQReal;

        double nashCoeff = getNashCoefficient(realQ, simQ, sumQReal, sumNum);

        StatisticsInfoDto statisticsInfo = new StatisticsInfoDto();
        statisticsInfo.setRelativeErrorOfSumQ(relativeErrorOfSumQ);
        statisticsInfo.setRelativeErrorOfPeak(relativeErrorOfPeak);
        statisticsInfo.setAbsoluteErrorOfPeakTime(absoluteErrorOfPeakTime);
        statisticsInfo.setNashCoeff(nashCoeff);
        return statisticsInfo;
    }

    public static StatisticsInfoV2Dto refreshStatisticsInfoV3(List<ForecastDataDto> data, Date fymdh) {
        StatisticsInfoV2Dto result = new StatisticsInfoV2Dto();
        int clen = 0;
        String unt = "H";
        if (data.size() > 1) {
            clen = CommonFun.getTimeStepMinutes(data.get(0).getDt(), data.get(1).getDt());
            unt = "M";
        }
        double sumQReal = 0;
        double sumQFore = 0;
        double peakQReal = 0;
        double peakQFore = 0;
        Date peakTimeQFore = null;
        Date peakTimeQReal = null;
        List<Double> qRealList = new LinkedList<>();
        List<Double> qForeList = new LinkedList<>();
        for (ForecastDataDto datum : data) {
            if (BooleanUtil.isTrue(datum.getQRealIsExist())) {
                if (peakQReal < datum.getQReal()) {
                    peakQReal = datum.getQReal();
                    peakTimeQReal = datum.getDt();
                }

                qRealList.add(datum.getQReal());
                sumQReal += datum.getQReal();
            }
            if (BooleanUtil.isTrue(datum.getQForeIsExist())) {
                if (peakQFore < datum.getQFore()) {
                    peakQFore = datum.getQFore();
                    peakTimeQFore = datum.getDt();
                }
                qForeList.add(datum.getQFore());
                if (!datum.equals(fymdh)) {
                    sumQFore += datum.getQFore();
                }
            }
        }
        //
        if (peakTimeQReal != null) {
            if (peakTimeQFore == null) {
                peakTimeQFore = data.get(0).getDt();
            }
            double absoluteErrorOfPeakTime =
                    DateUtil.between(peakTimeQFore, peakTimeQReal, DateUnit.HOUR, false) / clen;
            result.setAbsoluteErrorOfPeakTime(absoluteErrorOfPeakTime);
            result.setPeakQReal(peakQReal);
            result.setPeakTimeQReal(peakTimeQReal);
            result.setSumQReal(sumQReal * CommonFun.multiKFromFlowToVolumn(clen, unt) / 100); // 乘以系数之后转换为亿
            //
            double nashCoeff = getNashCoefficient(qRealList, qForeList, sumQReal, qForeList.size());
            result.setNashCoeff(nashCoeff);
            //
            double absoluteErrorOfSumQ = sumQFore - sumQReal;
            if (sumQReal == 0) {
                sumQReal = 0.00001;
            }
            double relativeErrorOfSumQ = 100 * absoluteErrorOfSumQ / sumQReal;
            result.setRelativeErrorOfSumQ(relativeErrorOfSumQ);
            //
            double absoluteErrorOfPeak = peakQFore - peakQReal;
            if (peakQReal == 0) {
                peakQReal = 0.00001;
            }
            double relativeErrorOfPeak = 100 * absoluteErrorOfPeak / peakQReal;
            result.setRelativeErrorOfPeak(relativeErrorOfPeak);
        }
        //
        result.setPeakQFore(peakQFore);
        result.setPeakTimeQFore(peakTimeQFore);
        result.setSumQFore(sumQFore * CommonFun.multiKFromFlowToVolumn(clen, unt) / 100);
        return result;
    }

    /**
     * 预见期预报 洪量、洪峰流量、峰现时间
     */
    public static StatisticsInfoDto refreshStatisticsFore(Date fymdh, List<ForecastDataDto> data) {
        double sumQForePrediction = 0;
        double peakQForePrediction = 0;
        int peakTimeQForePrediction = -1;
        int num = 0;
        int clen = 0;
        String unt = "H";
        if (data.size() > 1) {
            clen = CommonFun.getTimeStepMinutes(data.get(0).getDt(), data.get(1).getDt());
            unt = "M";
        }
        for (ForecastDataDto dataOne : data) {
            // 此处不必限制统计范围
            if (fymdh != null) {
                if (dataOne.getQSim() != null) {
                    if (dataOne.getDt().equals(fymdh)) {
                        peakQForePrediction = dataOne.getQSim();
                        peakTimeQForePrediction = 0;
                    }
                    if (dataOne.getDt().after(fymdh)) {
                        sumQForePrediction += dataOne.getQSim() * CommonFun.multiKFromFlowToVolumn(clen, unt);
                        if (peakQForePrediction < dataOne.getQSim()) {
                            peakQForePrediction = dataOne.getQSim();
                            peakTimeQForePrediction = num;
                        }
                    }
                }
            }
            num++;
        }
        StatisticsInfoDto statisticsInfo = new StatisticsInfoDto();
        statisticsInfo.setPredictionForecastSum(sumQForePrediction / 100); // 转换为亿
        statisticsInfo.setPredictionForecastPeak(peakQForePrediction);
        if (peakTimeQForePrediction >= 0) {
            statisticsInfo.setPredictionForecastPeakTime(data.get(peakTimeQForePrediction).getDt());
        }
        return statisticsInfo;
    }

    /**
     * 洪峰、洪量、峰现时间
     */
    public static List<StatisticsInfoDto> refreshStatisticsSum(List<StatisticsInfoDto> statisticsInfoList,
                                                               List<ForecastDataDto> data, Integer clen, String unt,
                                                               Date start, Date end, Double qSimLowerLimit) {
        double sumQFore = 0;
        double sumQForeMinusQLowerLimit = 0;
        double peakQFore = 0d;
        int peakTimeQFore = -1;
        if (start != null) {
            ForecastDataDto forecastDataDto = new ForecastDataDto();
            forecastDataDto.setQSim(0d);
            Double peakQForeFymdh =
                    data.stream().filter(temp -> temp.getDt().after(start)).findFirst().orElse(forecastDataDto)
                            .getQSim();
            if (Objects.nonNull(peakQForeFymdh)) {
                peakQFore = peakQForeFymdh;
                peakTimeQFore = 1;
            }
        }

        double maxQForeOneDay = -1;
        DateInterval maxQForeOneDayInterval = new DateInterval();
        double maxQForeThreeDays = -1;
        DateInterval maxQForeThreeDaysInterval = new DateInterval();
        double maxQForeFiveDays = -1;
        double maxQForeSevenDays = -1;
        DateInterval maxQForeSevenDaysInterval = new DateInterval();
        double maxQForeFifteenDays = -1;
        DateInterval maxQForeFifteenDaysInterval = new DateInterval();
        int num = 0;
        // 补充时段长 -- 计算洪量
        if (clen == null || unt == null) {
            if (data.size() > 1) {
                clen = CommonFun.getTimeStepMinutes(data.get(0).getDt(), data.get(1).getDt());
                unt = "M";
            } else {
                clen = 6;
                unt = "H";
            }
        }
        double totalDays = CommonFun.getDays(data.get(0).getDt(), data.get(data.size() - 1).getDt(), clen, unt);
        if (totalDays >= 1) {
            maxQForeOneDay = 0;
            if (totalDays >= 3) {
                maxQForeThreeDays = 0;
                if (totalDays >= 5) {
                    maxQForeFiveDays = 0;
                    if (totalDays >= 7) {
                        maxQForeSevenDays = 0;
                        if (totalDays >= 15) {
                            maxQForeFifteenDays = 0;
                        }
                    }
                }
            }
        }
        boolean statistics = false;
        // 洪量超定量值
        if (qSimLowerLimit == null) {
            statistics = true;
        }
        Date dtBeg = null;// 统计起始时间
        Date dtEnd = null;// 统计结束时间
        Date dt = null;// 判定时间 -- 判定统计是否完成
        for (ForecastDataDto dataOne : data) {
            // 记录时间
            dt = dataOne.getDt();
            // 统计条件：开始时间约束
            if (start != null && (dataOne.getDt().before(start) || dataOne.getDt().equals(start))) {
                num++;
                continue;
            }
            // 统计条件：结束时间约束
            if (end != null && dataOne.getDt().after(end)) {
                break;
            }
            if (dataOne.getQSim() != null) {
                if (qSimLowerLimit != null && dataOne.getQSim() >= qSimLowerLimit) {
                    statistics = true;
                }
                if (statistics) {
                    if (dtEnd == null) {
                        dtBeg = dataOne.getDt();
                    }
                    dtEnd = dataOne.getDt();
                    if (qSimLowerLimit != null && dataOne.getQSim() < qSimLowerLimit) {
                        statistics = false;
                        break;
                    }
                    sumQFore += dataOne.getQSim() * CommonFun.multiKFromFlowToVolumn(clen, unt);
                    if (qSimLowerLimit != null) {
                        sumQForeMinusQLowerLimit +=
                                (dataOne.getQSim() - qSimLowerLimit) * CommonFun.multiKFromFlowToVolumn(clen, unt);
                    }
                    if (peakQFore < dataOne.getQSim()) {
                        peakQFore = dataOne.getQSim();
                        peakTimeQFore = num;
                    }
                    // 1日洪量、3日洪量、5日洪量、7日洪量
                    if (maxQForeOneDay >= 0) {
                        Date dtForMax = null;
                        double temptMaxQForeOneDay = 0;
                        double temptMaxQForeThreeDays = 0;
                        double temptMaxQForeFiveDays = 0;
                        double temptMaxQForeSevenDays = 0;
                        double temptMaxQForeFifteenDays = 0;
                        for (ForecastDataDto dataOneForMax : data) {
                            if (dataOneForMax.getQSim() != null) {
                                dtForMax = dataOneForMax.getDt();
                                if (dtForMax.before(dt)) {
                                    continue;
                                }
                                double days = CommonFun.getDays(dt, dtForMax, clen, unt);
                                if (maxQForeOneDay >= 0) {
                                    if (days < 1) {
                                        temptMaxQForeOneDay +=
                                                dataOneForMax.getQSim() * CommonFun.multiKFromFlowToVolumn(clen, unt);
                                    }
                                    if (maxQForeThreeDays >= 0) {
                                        if (days < 3) {
                                            temptMaxQForeThreeDays += dataOneForMax.getQSim() *
                                                    CommonFun.multiKFromFlowToVolumn(clen, unt);
                                        }
                                        if (maxQForeFiveDays >= 0) {
                                            if (days < 5) {
                                                temptMaxQForeFiveDays += dataOneForMax.getQSim() *
                                                        CommonFun.multiKFromFlowToVolumn(clen, unt);
                                            }
                                            if (maxQForeSevenDays >= 0) {
                                                if (days < 7) {
                                                    temptMaxQForeSevenDays += dataOneForMax.getQSim() *
                                                            CommonFun.multiKFromFlowToVolumn(clen, unt);
                                                }
                                                if (maxQForeFifteenDays >= 0) {
                                                    if (days < 15) {
                                                        temptMaxQForeFifteenDays += dataOneForMax.getQSim() *
                                                                CommonFun.multiKFromFlowToVolumn(clen, unt);
                                                    } else {
                                                        break;
                                                    }
                                                } else {
                                                    if (days >= 7) {
                                                        break;
                                                    }
                                                }
                                            } else {
                                                if (days >= 5) {
                                                    break;
                                                }
                                            }
                                        } else {
                                            if (days >= 3) {
                                                break;
                                            }
                                        }
                                    } else {
                                        if (days >= 1) {
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        if (temptMaxQForeOneDay > maxQForeOneDay) {
                            maxQForeOneDay = temptMaxQForeOneDay;
                            maxQForeOneDayInterval.setStart(dt);
                            maxQForeOneDayInterval.setEnd(DateUtils.addDays(dt, 1));
                        }
                        if (maxQForeThreeDays >= 0 && temptMaxQForeThreeDays > maxQForeThreeDays) {
                            maxQForeThreeDays = temptMaxQForeThreeDays;
                            maxQForeThreeDaysInterval.setStart(dt);
                            maxQForeThreeDaysInterval.setEnd(DateUtils.addDays(dt, 3));
                        }
                        if (maxQForeFiveDays >= 0 && temptMaxQForeFiveDays > maxQForeFiveDays) {
                            maxQForeFiveDays = temptMaxQForeFiveDays;
                        }
                        if (maxQForeSevenDays >= 0 && temptMaxQForeSevenDays > maxQForeSevenDays) {
                            maxQForeSevenDays = temptMaxQForeSevenDays;
                            maxQForeSevenDaysInterval.setStart(dt);
                            maxQForeSevenDaysInterval.setEnd(DateUtils.addDays(dt, 7));
                        }
                        if (maxQForeFifteenDays >= 0 && temptMaxQForeFifteenDays > maxQForeFifteenDays) {
                            maxQForeFifteenDays = temptMaxQForeFifteenDays;
                            maxQForeFifteenDaysInterval.setStart(dt);
                            maxQForeFifteenDaysInterval.setEnd(DateUtils.addDays(dt, 15));
                        }
                    }
                }
            }
            num++;
        }
        if (peakTimeQFore >= 0) {
            StatisticsInfoDto statisticsInfo = new StatisticsInfoDto();
            statisticsInfo.setDtBeg(dtBeg);
            statisticsInfo.setDtEnd(dtEnd);
            statisticsInfo.setPeakQFore(peakQFore);
            statisticsInfo.setPeakTimeQForeIndex(peakTimeQFore);
            statisticsInfo.setPeakTimeQFore(data.get(peakTimeQFore).getDt());
            statisticsInfo.setSumQFore(sumQFore);
            if (qSimLowerLimit != null) {
                statisticsInfo.setSumQForeMinusQLowerLimit(sumQForeMinusQLowerLimit);
            }
            statisticsInfoList.add(statisticsInfo);
            if (maxQForeOneDay >= 0) {
                statisticsInfo.setMaxQForeOneDay(maxQForeOneDay);
                statisticsInfo.setMaxQForeOneDayInterval(maxQForeOneDayInterval);
                if (maxQForeThreeDays >= 0) {
                    statisticsInfo.setMaxQForeThreeDays(maxQForeThreeDays);
                    statisticsInfo.setMaxQForeThreeDaysInterval(maxQForeThreeDaysInterval);
                    if (maxQForeFiveDays >= 0) {
                        statisticsInfo.setMaxQForeFiveDays(maxQForeFiveDays);
                        if (maxQForeSevenDays >= 0) {
                            statisticsInfo.setMaxQForeSevenDays(maxQForeSevenDays);
                            statisticsInfo.setMaxQForeSevenDaysInterval(maxQForeSevenDaysInterval);
                            if (maxQForeFifteenDays >= 0) {
                                statisticsInfo.setMaxQForeFifteenDays(maxQForeFifteenDays);
                                statisticsInfo.setMaxQForeFifteenDaysInterval(maxQForeFifteenDaysInterval);
                            }
                        }
                    }
                }
            }
        }
        // 判定是否统计完成
        if (end != null && end.before(data.get(data.size() - 1).getDt())) {
            if (dt.before(end)) {
                refreshStatisticsSum(statisticsInfoList, data, clen, unt, dtEnd, end, qSimLowerLimit);
            }
        } else {
            if (dt.before(data.get(data.size() - 1).getDt())) {
                refreshStatisticsSum(statisticsInfoList, data, clen, unt, dtEnd, end, qSimLowerLimit);
            }
        }
        return statisticsInfoList;
    }

    public static StatisticsInfoDto refreshStatisticsSumForReservoir(List<ForecastDataDto> data, Integer clen,
                                                                     String unt, Date start, Date end) {
        double sumQIn = 0;
        double rzBeg = -99999;
        int num = 0;
        // 补充时段长 -- 计算洪量
        if (clen == null) {
            if (data.size() > 1) {
                clen = CommonFun.getMinutes(data.get(0).getDt(), data.get(1).getDt());
                unt = "M";
            } else {
                clen = 6;
                unt = "H";
            }
        }
        for (ForecastDataDto dataOne : data) {
            // 统计条件：开始时间约束
            if (start != null && dataOne.getDt().before(start)) {
                continue;
            } else {
                if (rzBeg == -99999) {
                    rzBeg = dataOne.getRz();
                }
            }
            // 统计条件：结束时间约束
            if (end != null && dataOne.getDt().after(end)) {
                break;
            }
            if (dataOne.getQIn() != null) {
                sumQIn += dataOne.getQIn() * CommonFun.multiKFromFlowToVolumn(clen, unt);
            }
            num++;
        }
        StatisticsInfoDto statisticsInfo = new StatisticsInfoDto();
        statisticsInfo.setSumQIn(sumQIn);
        statisticsInfo.setRzBeg(rzBeg);
        statisticsInfo.setStep(clen);
        statisticsInfo.setStepUnit(unt);
        statisticsInfo.setPeriods(num);
        return statisticsInfo;
    }

    /**
     * 纳什系数
     */
    private static double getNashCoefficient(List<ForecastDataDto> data, double sumQreal, int sumNum) {
        double nashCoeff = 0;
        double a = 0;
        double b = 0;
        double avgQreal = 0;
        avgQreal = sumQreal / sumNum;
        for (ForecastDataDto dataOne : data) {
            if (dataOne.getQReal() != null && dataOne.getQSim() != null) {
                a += Math.pow((dataOne.getQReal() - dataOne.getQSim()), 2);
                b += Math.pow((dataOne.getQReal() - avgQreal), 2);
            }
        }
        nashCoeff = 1 - a / b;
        return nashCoeff;
    }

    /**
     * 纳什系数
     */
    private static double getNashCoefficient(List<Double> realQ, List<Double> simQ, double sumQreal, int sumNum) {
        double nashCoeff = 0;
        double a = 0;
        double b = 0;
        double avgQreal = 0;
        avgQreal = sumQreal / sumNum;
        for (int i = 0; i < simQ.size(); i++) {
            if (realQ.size() > i && realQ.get(i) != null && simQ.get(i) != null) {
                a += Math.pow((realQ.get(i) - simQ.get(i)), 2);
                b += Math.pow((realQ.get(i) - avgQreal), 2);
            }
        }
        nashCoeff = 1 - a / b;
        return nashCoeff;
    }
}
